﻿//using Ionic.Zip;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.SharpZipLib.Zip;
using System.Diagnostics;
using ICSharpCode.SharpZipLib.Core;
using System.Windows.Forms;
using System.Net;

namespace IPBoss.MIS.UtilityHelper
{
    public  class FileToZip
    {
        /// <summary>   
        /// 创建一个Zip文件
        /// </summary>
        /// <param name="filesPath">需要打包的文件目录</param>
        /// <param name="zipFilePath">Zip文件保存路径</param>
        /// <param name="password">解压密码</param>
        public static void CreateZipFile(string filesPath, string zipFilePath, string password = "")
        {

            if (!Directory.Exists(filesPath))
            {
                throw new DirectoryNotFoundException(string.Format("Cannot find directory '{0}'", filesPath));
            }

            try
            {
                CreateZipFile(Directory.GetFiles(filesPath), zipFilePath, password);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 创建一个Zip文件
        /// </summary>
        /// <param name="files">需要打包的文件完整路径名称</param>
        /// <param name="zipFilePath">Zip文件保存路径</param>
        /// <param name="password">解压密码</param>
        public static void CreateZipFile(string[] fileNames, string zipFilePath, string password = "")
        {
            try
            {
                byte[] zipData = CreateZipFile(fileNames, password);
                if (zipData != null)
                {
                    using (var fs = new FileStream(zipFilePath, FileMode.OpenOrCreate))
                    {
                        fs.Write(zipData, 0, zipData.Length);
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 创建一个Zip文件流
        /// </summary>
        /// <param name="fileNames">压缩的文件集合</param>
        /// <param name="password"></param>
        /// <returns></returns>
        public static byte[] CreateZipFile(string[] fileNames, string password = "")
        {
            byte[] data = null;
            try
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    using (ZipOutputStream s = new ZipOutputStream(ms))
                    {

                        s.SetLevel(9); // 压缩级别 0-9
                        if (password.Length > 0)
                            s.Password = password; //Zip压缩文件密码
                        byte[] buffer = new byte[4096]; //缓冲区大小
                        foreach (string file in fileNames)
                        {
                            ZipEntry entry = new ZipEntry(Path.GetFileName(file));
                            entry.DateTime = DateTime.Now;
                            s.PutNextEntry(entry);
                            using (FileStream fs = File.OpenRead(file))
                            {
                                int sourceBytes;
                                do
                                {
                                    sourceBytes = fs.Read(buffer, 0, buffer.Length);
                                    s.Write(buffer, 0, sourceBytes);
                                } while (sourceBytes > 0);
                            }
                        }
                        s.Finish();
                        s.Close();
                    }
                    data = ms.ToArray();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return data;
        }

        /// <summary>
        /// 创建一个Zip文件流
        /// </summary>
        /// <param name="fileInfo">压缩的文件集合,key 文件名，value 完整路径</param>
        /// <param name="password"></param>
        /// <returns></returns>
        public static byte[] CreateZipFile(Dictionary<string, string> fileInfo, string password = "")
        {
            byte[] data = null;
            try
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    using (ZipOutputStream s = new ZipOutputStream(ms))
                    {

                        s.SetLevel(9); // 压缩级别 0-9
                        if (password.Length > 0)
                            s.Password = password; //Zip压缩文件密码
                        byte[] buffer = new byte[4096]; //缓冲区大小
                        foreach (var file in fileInfo)
                        {
                            ZipEntry entry = new ZipEntry(file.Key);
                            entry.DateTime = DateTime.Now;
                            s.PutNextEntry(entry);
                            using (FileStream fs = File.OpenRead(file.Value))
                            {
                                int sourceBytes;
                                do
                                {
                                    sourceBytes = fs.Read(buffer, 0, buffer.Length);
                                    s.Write(buffer, 0, sourceBytes);
                                } while (sourceBytes > 0);
                            }
                        }
                        s.Finish();
                        s.Close();
                    }
                    data = ms.ToArray();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return data;
        }


        public static List<byte[]> UnZipFileToByte(Stream inputStream, string password = "")
        {
            List<byte[]> fileData = new List<byte[]>();
            using (ZipInputStream s = new ZipInputStream(inputStream))
            {
                if (!string.IsNullOrEmpty(password))
                    s.Password = password; //Zip压缩文件密码
                ZipEntry theEntry;
                while ((theEntry = s.GetNextEntry()) != null)
                {
                    if (theEntry.Name != String.Empty)
                    {
                        using (MemoryStream ms = new MemoryStream())
                        {
                            s.CopyTo(ms);
                            fileData.Add(ms.ToArray());
                        }
                    }
                }
            }
            return fileData;
        }

        public static void UnZipFile(Stream inputStream, string unZipPath, string password = "")
        {
            // 解压路径如果不存在，创建
            if (!Directory.Exists(unZipPath))
                Directory.CreateDirectory(unZipPath);
            using (ZipInputStream s = new ZipInputStream(inputStream))
            {
                if (!string.IsNullOrEmpty(password))
                    s.Password = password; //Zip压缩文件密码
                ZipEntry theEntry;
                while ((theEntry = s.GetNextEntry()) != null)
                {
                    if (theEntry.Name != String.Empty)
                    {
                        using (FileStream streamWriter = new FileStream(Path.Combine(unZipPath, theEntry.Name), FileMode.OpenOrCreate))
                        {
                            byte[] data = new byte[2048];
                            int sourceBytes;
                            do
                            {
                                sourceBytes = s.Read(data, 0, data.Length);
                                streamWriter.Write(data, 0, sourceBytes);
                            } while (sourceBytes > 0);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 解压Zip文件
        /// </summary>
        /// <param name="zipFileName">zip文件完整路径名</param>
        /// <param name="unZipPath">解压保存路径</param>
        /// <param name="password"></param>
        public static void UnZipFile(string zipFileName, string unZipPath, string password = "")
        {
            if (!File.Exists(zipFileName))
            {
                throw new FileNotFoundException(string.Format("Cannot find file '{0}'", zipFileName));
            }
            UnZipFile(new FileStream(zipFileName, FileMode.Open), unZipPath, password);

        }

        /// <summary>
        /// 循环解压文件
        /// </summary>
        /// <param name="zipFileName"></param>
        /// <param name="unZipPath"></param>
        /// <returns></returns>
        public static string unZipFile(string zipFileName, string unZipPath)
        {
            string rootFile = " ";
            try
            {
                //读取压缩文件(zip文件)，准备解压缩
                ZipInputStream s = new ZipInputStream(File.OpenRead(zipFileName.Trim()));
                ZipEntry theEntry;
                string path = unZipPath;
                //解压出来的文件保存的路径
                string rootDir = " ";
                //根目录下的第一个子文件夹的名称
                while ((theEntry = s.GetNextEntry()) != null)
                {
                    rootDir = Path.GetDirectoryName(theEntry.Name);
                    //得到根目录下的第一级子文件夹的名称
                    if (rootDir.IndexOf("\\") >= 0)
                    {
                        rootDir = rootDir.Substring(0, rootDir.IndexOf("\\") + 1);
                    }
                    string dir = Path.GetDirectoryName(theEntry.Name);
                    //根目录下的第一级子文件夹的下的文件夹的名称
                    string fileName = Path.GetFileName(theEntry.Name);
                    //根目录下的文件名称
                    if (dir != " ")
                    //创建根目录下的子文件夹,不限制级别
                    {
                        if (!Directory.Exists(unZipPath + "\\" + dir))
                        {
                            path = unZipPath + "\\" + dir;
                            //在指定的路径创建文件夹
                            Directory.CreateDirectory(path);
                        }
                    }
                    else if (dir == " " && fileName != "")
                    //根目录下的文件
                    {
                        path = unZipPath;
                        rootFile = fileName;
                    }
                    else if (dir != " " && fileName != "")
                    //根目录下的第一级子文件夹下的文件
                    {
                        if (dir.IndexOf("\\") > 0)
                        //指定文件保存的路径
                        {
                            path = unZipPath + "\\" + dir;
                        }
                    }
                    if (dir == rootDir)
                    //判断是不是需要保存在根目录下的文件
                    {
                        path = unZipPath + "\\" + rootDir;
                    }
                    //以下为解压缩zip文件的基本步骤
                    //基本思路就是遍历压缩文件里的所有文件，创建一个相同的文件。
                    if (fileName != String.Empty)
                    {
                        FileStream streamWriter = File.Create(path + "\\" + fileName);
                        int size = 2048;
                        byte[] data = new byte[2048];
                        while (true)
                        {
                            size = s.Read(data, 0, data.Length);
                            if (size > 0)
                            {
                                streamWriter.Write(data, 0, size);
                            }
                            else
                            {
                                break;
                            }
                        }
                        streamWriter.Close();
                    }
                }
                s.Close();
                return rootFile;
            }
            catch (Exception ex)
            {
                return "1; " + ex.Message;
            }
        }


        /// <summary>
        /// 解压完成后返回文件列表信息
        /// </summary>
        /// <param name="zipFileName"></param>
        /// <param name="unZipPath"></param>
        /// <returns></returns>
        public static List<string> unZipFileList(string zipFileName, string unZipPath)
        {
            string rootFile = " ";
            List<string> fileNameList = new List<string>();
            try
            {
                //读取压缩文件(zip文件)，准备解压缩
                ZipInputStream s = new ZipInputStream(File.OpenRead(zipFileName.Trim()));
                ZipEntry theEntry;
                string path = unZipPath;
                //解压出来的文件保存的路径
                string rootDir = " ";
                //根目录下的第一个子文件夹的名称
                while ((theEntry = s.GetNextEntry()) != null)
                {
                    rootDir = Path.GetDirectoryName(theEntry.Name);
                    //得到根目录下的第一级子文件夹的名称
                    if (rootDir.IndexOf("\\") >= 0)
                    {
                        rootDir = rootDir.Substring(0, rootDir.IndexOf("\\") + 1);
                    }
                    string dir = Path.GetDirectoryName(theEntry.Name);
                    //根目录下的第一级子文件夹的下的文件夹的名称
                    string fileName = Path.GetFileName(theEntry.Name);
                    //根目录下的文件名称
                    if (dir != " ")
                    //创建根目录下的子文件夹,不限制级别
                    {
                        if (!Directory.Exists(unZipPath + "\\" + dir))
                        {
                            path = unZipPath + "\\" + dir;
                            //在指定的路径创建文件夹
                            Directory.CreateDirectory(path);
                        }
                    }
                    else if (dir == " " && fileName != "")
                    //根目录下的文件
                    {
                        path = unZipPath;
                        rootFile = fileName;
                    }
                    else if (dir != " " && fileName != "")
                    //根目录下的第一级子文件夹下的文件
                    {
                        if (dir.IndexOf("\\") > 0)
                        //指定文件保存的路径
                        {
                            path = unZipPath + "\\" + dir;
                        }
                    }
                    if (dir == rootDir)
                    //判断是不是需要保存在根目录下的文件
                    {
                        path = unZipPath + "\\" + rootDir;
                    }
                    //以下为解压缩zip文件的基本步骤
                    //基本思路就是遍历压缩文件里的所有文件，创建一个相同的文件。
                    if (fileName != String.Empty)
                    {
                        FileStream streamWriter = File.Create(path + "\\" + fileName);
                        int size = 2048;
                        byte[] data = new byte[2048];
                        while (true)
                        {
                            size = s.Read(data, 0, data.Length);
                            if (size > 0)
                            {
                                streamWriter.Write(data, 0, size);
                            }
                            else
                            {
                                break;
                            }
                        }
                        streamWriter.Close();
                        fileNameList.Add(path + "\\" + fileName);
                    }
                }
                s.Close();
                return fileNameList;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="URL">下载文件地址</param>
        /// <param name="Filename">下载后的存放地址</param>
        /// <param name="Prog">用于显示的进度条</param>
        public static void DownloadFile(string URL, string filename, System.Windows.Forms.ProgressBar prog)
        {
            try
            {
                progressBar1 = prog;

                System.Net.HttpWebRequest Myrq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(URL);
                System.Net.HttpWebResponse myrp = (System.Net.HttpWebResponse)Myrq.GetResponse();
                long totalBytes = myrp.ContentLength;

                if (prog != null)
                {
                    SetprogressResult(totalBytes.ToString(), 2);
                    //prog.Maximum = (int)totalBytes;
                }
                System.IO.Stream st = myrp.GetResponseStream();
                System.IO.Stream so = new System.IO.FileStream(filename, System.IO.FileMode.Create);
                long totalDownloadedByte = 0;
                byte[] by = new byte[1024];
                int osize = st.Read(by, 0, (int)by.Length);
                while (osize > 0)
                {
                    totalDownloadedByte = osize + totalDownloadedByte;
                    System.Windows.Forms.Application.DoEvents();
                    so.Write(by, 0, osize);

                    if (prog != null)
                    {

                        SetprogressResult((totalDownloadedByte - ((int)(totalDownloadedByte * 0.1))).ToString(), 1);
                        //prog.Value = (int)(totalDownloadedByte - (totalDownloadedByte * 0.1));
                    }
                    osize = st.Read(by, 0, (int)by.Length);
                }
                so.Close();
                st.Close();
            }
            catch (System.Exception)
            {
                throw;
            }
        }

        public static ProgressBar progressBar1;
        public delegate void SetlabTextHandler(string result, int type);
        /// <summary>
        /// 更改 进度条
        /// </summary>
        /// <param name="result"></param>
        private static void SetprogressResult(string result, int type)
        {
            if (progressBar1.InvokeRequired == true)
            {

                SetlabTextHandler set = new SetlabTextHandler(SetprogressResult);//委托的方法参数应和SetCalResult一致  
                progressBar1.Invoke(set, new object[] { result, type }); //此方法第二参数用于传入方法,代替形参result  

            }
            else
            {
                if (type == 1)
                {
                    progressBar1.Value = int.Parse(result);
                }
                else
                {
                    progressBar1.Maximum = int.Parse(result);
                }
            }
        }
    }
}
